<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VDO.Ninja SDK - TURN Only Mode Example</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #f5f5f5;
        }
        .container {
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .section {
            margin: 20px 0;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 8px;
        }
        .info-box {
            background: #e3f2fd;
            border-left: 4px solid #2196f3;
            padding: 15px;
            margin: 20px 0;
        }
        .warning-box {
            background: #fff3cd;
            border-left: 4px solid #ffc107;
            padding: 15px;
            margin: 20px 0;
        }
        button {
            background: #007bff;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            margin: 5px;
            font-size: 16px;
        }
        button:hover {
            background: #0056b3;
        }
        button:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
        input, select {
            padding: 8px;
            margin: 5px;
            border: 1px solid #ddd;
            border-radius: 4px;
            width: 200px;
        }
        video {
            width: 100%;
            max-width: 640px;
            height: auto;
            background: #000;
            margin: 10px 0;
        }
        .status {
            padding: 10px;
            margin: 10px 0;
            background: #f8f9fa;
            border-radius: 4px;
            font-family: monospace;
            font-size: 14px;
        }
        .candidate-list {
            max-height: 200px;
            overflow-y: auto;
            background: #f8f9fa;
            border: 1px solid #ddd;
            border-radius: 4px;
            padding: 10px;
            margin: 10px 0;
            font-family: monospace;
            font-size: 12px;
        }
        .candidate {
            margin: 2px 0;
            padding: 2px;
        }
        .candidate.host { color: #28a745; }
        .candidate.srflx { color: #17a2b8; }
        .candidate.relay { color: #dc3545; }
        code {
            background: #f8f9fa;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: monospace;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>VDO.Ninja SDK - TURN Only Mode Example</h1>
        
        <div class="info-box">
            <h3>What is TURN-Only Mode?</h3>
            <p>TURN-only mode (relay mode) forces all WebRTC traffic through a TURN server, bypassing direct peer-to-peer connections. This is useful for:</p>
            <ul>
                <li>Testing TURN server functionality</li>
                <li>Ensuring privacy by hiding IP addresses</li>
                <li>Corporate networks with strict firewall rules</li>
                <li>Scenarios requiring traffic to go through specific servers</li>
            </ul>
        </div>
        
        <div class="warning-box">
            <h3>⚠️ Important Notes</h3>
            <ul>
                <li>TURN-only mode requires valid TURN server credentials</li>
                <li>Connection quality may be lower due to relay overhead</li>
                <li>Bandwidth costs increase as all traffic goes through TURN</li>
                <li>The default TURN servers may have usage limits</li>
            </ul>
        </div>
        
        <!-- Configuration Section -->
        <div class="section">
            <h2>Configuration</h2>
            
            <label>ICE Transport Policy:</label>
            <select id="icePolicy">
                <option value="all">All (Default - Direct + TURN)</option>
                <option value="relay">Relay Only (TURN Only)</option>
            </select>
            
            <br><br>
            
            <label>Custom TURN Server (optional):</label><br>
            <input type="text" id="turnUrl" placeholder="turn:turn.example.com:3478" style="width: 300px;"><br>
            <input type="text" id="turnUser" placeholder="Username"><br>
            <input type="password" id="turnPass" placeholder="Password"><br>
            
            <button onclick="testConfiguration()">Test Configuration</button>
        </div>
        
        <!-- ICE Candidates Monitor -->
        <div class="section">
            <h2>ICE Candidates Monitor</h2>
            <p>This shows what types of ICE candidates are being gathered:</p>
            
            <button onclick="startCandidateTest()" id="candidateTestBtn">Start Candidate Test</button>
            <button onclick="stopCandidateTest()" id="stopCandidateBtn" disabled>Stop Test</button>
            
            <div id="candidateStatus" class="status">Ready to test...</div>
            <div id="candidateList" class="candidate-list">
                <em>No candidates collected yet</em>
            </div>
            
            <div id="candidateSummary" style="margin-top: 10px;">
                <strong>Summary:</strong>
                <span id="hostCount">Host: 0</span> | 
                <span id="srflxCount">Server Reflexive: 0</span> | 
                <span id="relayCount">Relay: 0</span>
            </div>
        </div>
        
        <!-- Connection Test -->
        <div class="section">
            <h2>TURN Connection Test</h2>
            <p>Test actual connection establishment using selected ICE policy:</p>
            
            <input type="text" id="roomName" placeholder="Room name" value="turn-test-room">
            <button onclick="startConnectionTest()" id="connectTestBtn">Start Connection Test</button>
            <button onclick="stopConnectionTest()" id="stopConnectBtn" disabled>Stop Test</button>
            
            <div id="connectionStatus" class="status">Ready to test...</div>
            
            <div style="display: flex; gap: 20px; margin-top: 20px;">
                <div style="flex: 1;">
                    <h3>Publisher</h3>
                    <video id="pubVideo" autoplay playsinline muted></video>
                    <div id="pubStats" class="status">-</div>
                </div>
                <div style="flex: 1;">
                    <h3>Viewer</h3>
                    <video id="viewVideo" autoplay playsinline></video>
                    <div id="viewStats" class="status">-</div>
                </div>
            </div>
        </div>
        
        <!-- Code Examples -->
        <div class="section">
            <h2>Code Examples</h2>
            
            <h3>1. Basic TURN-Only Configuration</h3>
            <pre><code>const sdk = new VDONinjaSDK({
    iceTransportPolicy: 'relay',  // Forces TURN-only mode
    turnServers: [
        {
            urls: 'turn:your-turn-server.com:3478',
            username: 'your-username',
            credential: 'your-password'
        }
    ]
});</code></pre>
            
            <h3>2. Quick View with TURN-Only</h3>
            <pre><code>const sdk = new VDONinjaSDK({ 
    iceTransportPolicy: 'relay' 
});

const { pc, cleanup } = await sdk.quickView({
    streamID: 'some-stream',
    room: 'secure-room'
});

// All connections will use TURN relay</code></pre>
            
            <h3>3. Detecting Connection Type</h3>
            <pre><code>pc.onicecandidate = (event) => {
    if (event.candidate) {
        const candidate = event.candidate.candidate;
        
        if (candidate.includes('typ host')) {
            console.log('Host candidate (direct)');
        } else if (candidate.includes('typ srflx')) {
            console.log('Server reflexive (STUN)');
        } else if (candidate.includes('typ relay')) {
            console.log('Relay candidate (TURN)');
        }
    }
};</code></pre>
        </div>
    </div>

    <script src="../vdoninja-sdk.js"></script>
    <script>
        let testSDK = null;
        let pubSDK = null;
        let viewSDK = null;
        let candidateStats = { host: 0, srflx: 0, relay: 0 };
        
        // Test configuration
        async function testConfiguration() {
            const policy = document.getElementById('icePolicy').value;
            const turnUrl = document.getElementById('turnUrl').value;
            const turnUser = document.getElementById('turnUser').value;
            const turnPass = document.getElementById('turnPass').value;
            
            console.log('Testing configuration:', { policy, turnUrl });
            
            // Build config
            const config = {
                debug: true,
                iceTransportPolicy: policy
            };
            
            // Add custom TURN if provided
            if (turnUrl && turnUser && turnPass) {
                config.turnServers = [{
                    urls: turnUrl,
                    username: turnUser,
                    credential: turnPass
                }];
            }
            
            try {
                const sdk = new VDONinjaSDK(config);
                await sdk.connect();
                
                // Create a test connection to check config
                const conn = sdk._createConnection('test', 'publisher');
                const pcConfig = conn.pc.getConfiguration();
                
                console.log('RTCPeerConnection config:', pcConfig);
                alert(`Configuration valid!\n\nICE Policy: ${pcConfig.iceTransportPolicy || 'all'}\nICE Servers: ${pcConfig.iceServers.length}`);
                
                conn.pc.close();
                await sdk.disconnect();
                
            } catch (error) {
                alert(`Configuration error: ${error.message}`);
            }
        }
        
        // Start candidate collection test
        async function startCandidateTest() {
            const policy = document.getElementById('icePolicy').value;
            const status = document.getElementById('candidateStatus');
            const list = document.getElementById('candidateList');
            
            // Reset stats
            candidateStats = { host: 0, srflx: 0, relay: 0 };
            updateCandidateSummary();
            
            status.textContent = `Starting candidate test with policy: ${policy}`;
            list.innerHTML = '';
            
            try {
                testSDK = new VDONinjaSDK({
                    debug: true,
                    iceTransportPolicy: policy
                });
                
                await testSDK.connect();
                
                // Create a dummy connection to gather candidates
                const conn = testSDK._createConnection('test', 'publisher');
                
                conn.pc.onicecandidate = (event) => {
                    if (event.candidate) {
                        const candidate = event.candidate.candidate;
                        let type = 'unknown';
                        let className = '';
                        
                        if (candidate.includes('typ host')) {
                            type = 'HOST';
                            className = 'host';
                            candidateStats.host++;
                        } else if (candidate.includes('typ srflx')) {
                            type = 'SRFLX';
                            className = 'srflx';
                            candidateStats.srflx++;
                        } else if (candidate.includes('typ relay')) {
                            type = 'RELAY';
                            className = 'relay';
                            candidateStats.relay++;
                        }
                        
                        const candidateDiv = document.createElement('div');
                        candidateDiv.className = `candidate ${className}`;
                        candidateDiv.textContent = `[${type}] ${candidate}`;
                        list.appendChild(candidateDiv);
                        
                        updateCandidateSummary();
                    }
                };
                
                // Create offer to start gathering
                await conn.pc.createOffer();
                
                status.textContent = `Gathering candidates with policy: ${policy}`;
                
                document.getElementById('candidateTestBtn').disabled = true;
                document.getElementById('stopCandidateBtn').disabled = false;
                
            } catch (error) {
                status.textContent = `Error: ${error.message}`;
                stopCandidateTest();
            }
        }
        
        // Stop candidate test
        async function stopCandidateTest() {
            if (testSDK) {
                await testSDK.disconnect();
                testSDK = null;
            }
            
            document.getElementById('candidateStatus').textContent = 'Test stopped';
            document.getElementById('candidateTestBtn').disabled = false;
            document.getElementById('stopCandidateBtn').disabled = true;
        }
        
        // Update candidate summary
        function updateCandidateSummary() {
            document.getElementById('hostCount').textContent = `Host: ${candidateStats.host}`;
            document.getElementById('srflxCount').textContent = `Server Reflexive: ${candidateStats.srflx}`;
            document.getElementById('relayCount').textContent = `Relay: ${candidateStats.relay}`;
        }
        
        // Start connection test
        async function startConnectionTest() {
            const policy = document.getElementById('icePolicy').value;
            const room = document.getElementById('roomName').value;
            const status = document.getElementById('connectionStatus');
            
            if (!room) {
                alert('Please enter a room name');
                return;
            }
            
            status.textContent = `Starting connection test with policy: ${policy}`;
            
            try {
                // Get user media
                const stream = await navigator.mediaDevices.getUserMedia({ 
                    video: true, 
                    audio: true 
                });
                
                document.getElementById('pubVideo').srcObject = stream;
                
                // Publisher SDK
                pubSDK = new VDONinjaSDK({
                    debug: true,
                    iceTransportPolicy: policy
                });
                
                const { streamID, cleanup: pubCleanup } = await pubSDK.quickPublish({
                    stream,
                    room,
                    label: `TURN Test - ${policy}`
                });
                
                status.textContent = `Publisher ready: ${streamID}. Starting viewer...`;
                
                // Give publisher time to be ready
                await new Promise(resolve => setTimeout(resolve, 2000));
                
                // Viewer SDK
                viewSDK = new VDONinjaSDK({
                    debug: true,
                    iceTransportPolicy: policy
                });
                
                const { pc, cleanup: viewCleanup } = await viewSDK.quickView({
                    streamID,
                    room
                });
                
                // Monitor connection
                pc.ontrack = (event) => {
                    document.getElementById('viewVideo').srcObject = event.streams[0];
                };
                
                pc.onconnectionstatechange = () => {
                    status.textContent = `Connection state: ${pc.connectionState}`;
                    updateConnectionStats(pc);
                };
                
                // Monitor ICE connection specifically
                pc.oniceconnectionstatechange = () => {
                    console.log(`ICE state: ${pc.iceConnectionState}`);
                };
                
                document.getElementById('connectTestBtn').disabled = true;
                document.getElementById('stopConnectBtn').disabled = false;
                
            } catch (error) {
                status.textContent = `Error: ${error.message}`;
                stopConnectionTest();
            }
        }
        
        // Stop connection test
        async function stopConnectionTest() {
            const status = document.getElementById('connectionStatus');
            
            // Stop video tracks
            const pubVideo = document.getElementById('pubVideo');
            if (pubVideo.srcObject) {
                pubVideo.srcObject.getTracks().forEach(track => track.stop());
                pubVideo.srcObject = null;
            }
            
            document.getElementById('viewVideo').srcObject = null;
            
            // Disconnect SDKs
            if (pubSDK) {
                await pubSDK.disconnect();
                pubSDK = null;
            }
            
            if (viewSDK) {
                await viewSDK.disconnect();
                viewSDK = null;
            }
            
            status.textContent = 'Test stopped';
            document.getElementById('pubStats').textContent = '-';
            document.getElementById('viewStats').textContent = '-';
            
            document.getElementById('connectTestBtn').disabled = false;
            document.getElementById('stopConnectBtn').disabled = true;
        }
        
        // Update connection statistics
        async function updateConnectionStats(pc) {
            try {
                const stats = await pc.getStats();
                let candidateType = 'Unknown';
                
                stats.forEach(report => {
                    if (report.type === 'candidate-pair' && report.state === 'succeeded') {
                        // Get the selected candidate pair
                        stats.forEach(candidate => {
                            if (candidate.type === 'local-candidate' && candidate.id === report.localCandidateId) {
                                candidateType = candidate.candidateType.toUpperCase();
                            }
                        });
                    }
                });
                
                document.getElementById('viewStats').textContent = `Connected via: ${candidateType}`;
                
            } catch (error) {
                console.error('Stats error:', error);
            }
        }
    </script>
</body>
</html>